use chrono::Local;
use jsonwebtoken::{decode, DecodingKey, encode, EncodingKey, Header, Validation};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use common::error::MyError;

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Claims {
    pub sub: String,
    pub uid: i64,
    pub company: String,
    pub exp: usize,
}

static SECRET: Lazy<String> = Lazy::new(|| Uuid::new_v4().to_string());

pub fn gen_jwt_token(sub: String, uid: i64) -> Result<String, MyError> {
    let claims = Claims {
        sub,
        uid,
        exp: (Local::now().timestamp() + 120 * 60) as usize,
        ..Default::default()
    };
    // 准备加密 key
    let encoding_key = EncodingKey::from_secret(SECRET.as_ref());
    // 生成 token
    let jwt_token = encode(&Header::default(), &claims, &encoding_key);
    match jwt_token {
        Ok(jwt_token) => Ok(jwt_token),
        Err(_) => Err(MyError::UnauthorizedError("gen token fail".to_string())),
    }
}

pub fn validation_jwt_token(token: &str) -> Result<Claims, MyError> {
    // 准备解密 key
    let decoding_key = &DecodingKey::from_secret(SECRET.as_ref());
    let token_data = decode::<Claims>(token, decoding_key, &Validation::default());
    match token_data {
        Ok(token_data) => Ok(token_data.claims),
        Err(err) => Err(MyError::UnauthorizedError(format!(
            "解析令牌失败:{}",
            err.to_string()
        ))),
    }
}
